#include "com.h"

int open_port(const char* dev_path)
{
    int fd;

    //open uart
    fd = open(dev_path, O_RDWR|O_NOCTTY|O_NDELAY);
    if(fd < 0)
    {
        perror("open serial port");
        return -1;
    }
    if(fcntl(fd, F_SETFL, 0) < 0)
        perror("fcntl F_SETFL\n");
    /*if(isatty(STDIN_FILENO) == 0)
    {
        perror("standard inpput is not a terminal device");
    }*/

    return fd;
}

int set_com_config(int fd, int baud_rate, int data_bits, char parity, int stop_bits)
{
    struct termios new_cfg, old_cfg;
    int speed;
    int returnvalue;

    returnvalue = tcgetattr(fd, &old_cfg);//save current uart configure
    if(returnvalue < 0)
    {
        perror("tcgetattr:tcsetattr()1");
        return -1;
    }

    new_cfg = old_cfg;//why?Maybe don't need
    cfmakeraw(&new_cfg);//config as orignal mode: recevice byte one by one
    new_cfg.c_cflag &= ~CSIZE;//clear c_cflag

    switch(baud_rate)
    {
    case 2400:
        speed = B2400;break;
    case 4800:
        speed = B4800;break;
    case 9600:
        speed = B9600;break;
    case 19200:
        speed = B19200;break;
    case 38400:
        speed = B38400;break;    
    default:
    case 115200:
        speed = B115200;break;
    }
    cfsetispeed(&new_cfg, speed);//set in baud_rate
    cfsetospeed(&new_cfg, speed);//set out baud_rate;

    switch(data_bits)//set data bits
    {
    case 7:
        new_cfg.c_cflag |= CS7;break;
    default:
    case 8:
        new_cfg.c_cflag |= CS8;break;
    }

    switch(parity)//set parity
    {
    default:
    case 's':
    case 'S':
    {
        new_cfg.c_cflag &= ~PARENB;
        new_cfg.c_cflag &= ~INPCK;
    }break;

    case 'o':
    case 'O':
    {
        new_cfg.c_cflag |= (PARODD | PARENB);
        new_cfg.c_cflag |= INPCK;
    }break;

    case 'e':
    case 'E':
    {
        new_cfg.c_cflag |= PARENB;
        new_cfg.c_cflag &= ~PARODD;
        new_cfg.c_cflag |= INPCK;
    }break;

    case 'n':
    case 'N':
    {
        new_cfg.c_cflag &= ~PARENB;
        new_cfg.c_cflag &= ~CSTOPB;
    }break;

    }

    switch(stop_bits)//set stop bits
    {
    default:
    case 1:
        new_cfg.c_cflag &= ~CSTOPB;break;
    case 2:
        new_cfg.c_cflag |= CSTOPB;break;
    }

    //set wait time and min recevice byte
    new_cfg.c_cc[VTIME] = 0;
    new_cfg.c_cc[VMIN] = 67;//1

    tcflush(fd, TCIFLUSH);//process unrecevice byte

    returnvalue = tcsetattr(fd, TCSANOW, &new_cfg);//use new configure
    if(returnvalue < 0)
    {
        perror("tcsetattr:tcsetattr()2");
        return -1;
    }

    return 0;
}
